﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Text.RegularExpressions;
using FoundationLib.Common.Extensions;

namespace FoundationLib.Web.Mvc
{
	/// <summary>
	/// Provides extensions for HTML encoding.
	/// </summary>
	public static class EncodeHelper
	{
		/// <summary>
		/// The link regular expression pattern
		/// </summary>
		private const string URL_PATTERN = @"(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?";


		/// <summary>
		/// Encodes the given string value.
		/// </summary>
		/// <param name="helper">The HTML helper</param>
		/// <param name="value">The string value to encode</param>
		/// <param name="preserveLineBreaks">A value indicating whether line breaks should be preserved</param>
		/// <returns>The encoded string</returns>
		public static string Encode(this HtmlHelper helper, string value, bool preserveLineBreaks)
		{
			return Encode(helper, (object)value, preserveLineBreaks);
		}

		/// <summary>
		/// Encodes the given object.
		/// </summary>
		/// <param name="helper">The HTML helper</param>
		/// <param name="value">The input object</param>
		/// <param name="preserveLineBreaks">A value indicating whether line breaks should be preserved</param>
		/// <returns>An encoded string representing the input</returns>
		public static string Encode(this HtmlHelper helper, object value, bool preserveLineBreaks)
		{
			return Encode(helper, value, HtmlEncodeOptions.PreserveLineBreaks);
		}

		/// <summary>
		/// Encodes the given input string.
		/// </summary>
		/// <param name="helper">The HTML helper</param>
		/// <param name="value">The input string</param>
		/// <param name="options">A set of HTML encode options to be used</param>
		/// <returns>The encoded string</returns>
		public static string Encode(this HtmlHelper helper, string value, HtmlEncodeOptions options)
		{
			return Encode(helper, (object)value, options);
		}

		/// <summary>
		/// Encodes the given input.
		/// </summary>
		/// <param name="helper">The HTML helper</param>
		/// <param name="value">The input object</param>
		/// <param name="options">A set of HTML encode options to be used</param>
		/// <returns>An encoded string representing the input</returns>
		public static string Encode(this HtmlHelper helper, object value, HtmlEncodeOptions options)
		{
			string result = helper.Encode(value);

			if (options.HasFlag(HtmlEncodeOptions.PreserveLineBreaks))
			{
				result = result.Replace(Environment.NewLine, "<br/>");
			}
			if (options.HasFlag(HtmlEncodeOptions.PreserveWhiteSpace))
			{
				result = result.Replace(" ", "&nbsp;");
			}
			if (options.HasFlag(HtmlEncodeOptions.ParseUrls))
			{
				Regex regex = new Regex(URL_PATTERN);
				MatchCollection matches = regex.Matches(result);
				string format = "<a href='{0}' target='_blank' title='{0}'>{1}</a>";

				foreach (Match match in matches)
				{
					string displayUrl = null;
					if (match.Value.Length > 50)
					{
						displayUrl = match.Value.Substring(0, 50) + "...";
					}
					else
					{
						displayUrl = match.Value;
					}
					result = regex.Replace(result, String.Format(format, match.Value, displayUrl), 1, match.Index);
				}
			}

			return result;
		}
	}
}
